import type { GlobalThemeOverrides } from 'naive-ui';
import { getColorByColorPaletteNumber, getColorPalette } from '@sa/color-palette';
import { addColorAlpha, getRgbOfColor } from '@sa/utils';
import { overrideThemeSettings, themeSettings } from '@/theme/settings';
import { themeVars } from '@/theme/vars';
import { localStg } from '@/utils/storage';

const DARK_CLASS = 'dark';

/** Init theme settings */
export function initThemeSettings() {
  // const isProd = import.meta.env.PROD;

  // if it is development mode, the theme settings will not be cached, by update `themeSettings` in `src/theme/settings.ts` to update theme settings
  // if (!isProd) return themeSettings;

  // if it is production mode, the theme settings will be cached in localStorage
  // if want to update theme settings when publish new version, please update `overrideThemeSettings` in `src/theme/settings.ts`

  const settings = localStg.get('themeSettings') || themeSettings;

  const isOverride = localStg.get('overrideThemeFlag') === BUILD_TIME;

  if (!isOverride) {
    Object.assign(settings, overrideThemeSettings);
    localStg.set('overrideThemeFlag', BUILD_TIME);
  }
  return settings;
}

/**
 * Create theme token
 *
 * @param colors Theme colors
 */
export function createThemeToken(colors: App.Theme.ThemeColor) {
  const paletteColors = createThemePaletteColors(colors);

  const themeTokens: App.Theme.ThemeToken = {
    colors: {
      ...paletteColors,
      nprogress: paletteColors.primary,
      siderbar: 'rgb(255, 255, 255)',
      header: 'rgb(245, 248, 251)',
      layout: 'rgb(239, 242, 245)',
      inverted: 'rgb(0, 20, 40)',
      siderbar_text: 'rgb(35, 40, 51)',
      base_text: 'rgb(3, 7, 18)', // 基础文本色
      light_text: 'rgb(79, 86, 102)', // 浅色文本色
      content_bg: 'rgb(245, 248, 251)', // 内容背景色
      content_hover: 'rgb(232, 238, 247)',

      table_th: 'rgb(245, 248, 251)', // 表格
      table_td: 'rgb(255, 255, 255)' // 表格
    },
    boxShadow: {
      header: '0 1px 2px rgb(0, 21, 41, 0.08)',
      sider: '2px 0 8px 0 rgb(29, 35, 41, 0.05)',
      tab: '0 1px 2px rgb(0, 21, 41, 0.08)'
    }
  };

  const darkThemeTokens: App.Theme.ThemeToken = {
    colors: {
      ...themeTokens.colors,
      header: 'rgb(25, 28, 42)', // 顶栏背景色
      siderbar: 'rgb(18, 20, 32)', // 侧边栏
      layout: 'rgb(15, 16, 27)', // 页面背景色
      siderbar_text: 'rgb(206, 206, 220)',
      base_text: 'rgb(245, 245, 245)',
      light_text: 'rgb(164, 164, 176)', // 浅色文本色
      content_bg: 'rgb(21, 23, 36)', // 内容背景色
      content_hover: 'rgb(46, 50, 70)',

      table_th: 'rgb(25, 28, 42)', // 表格
      table_td: 'rgb(21, 23, 36)' // 表格
    },
    boxShadow: {
      ...themeTokens.boxShadow
    }
  };

  return {
    themeTokens,
    darkThemeTokens
  };
}

/**
 * Create theme palette colors
 *
 * @param colors Theme colors
 */
function createThemePaletteColors(colors: App.Theme.ThemeColor) {
  const colorKeys = Object.keys(colors) as App.Theme.ThemeColorKey[];
  const colorPaletteVar = {} as App.Theme.ThemePaletteColor;

  colorKeys.forEach(key => {
    const { palettes, main } = getColorPalette(colors[key], key);

    colorPaletteVar[key] = main.hexcode;

    palettes.forEach(item => {
      colorPaletteVar[`${key}-${item.number}`] = item.hexcode;
    });
  });

  return colorPaletteVar;
}

/**
 * Get css var by tokens
 *
 * @param tokens Theme base tokens
 */
function getCssVarByTokens(tokens: App.Theme.BaseToken) {
  const styles: string[] = [];

  function removeVarPrefix(value: string) {
    return value.replace('var(', '').replace(')', '');
  }

  function removeRgbPrefix(value: string) {
    return value.replace('rgb(', '').replace(')', '');
  }

  for (const [key, tokenValues] of Object.entries(themeVars)) {
    for (const [tokenKey, tokenValue] of Object.entries(tokenValues)) {
      let cssVarsKey = removeVarPrefix(tokenValue);
      let cssValue = tokens[key][tokenKey];

      if (key === 'colors') {
        cssVarsKey = removeRgbPrefix(cssVarsKey);
        const { r, g, b } = getRgbOfColor(cssValue);
        cssValue = `${r} ${g} ${b}`;
      }

      styles.push(`${cssVarsKey}: ${cssValue}`);
    }
  }

  const styleStr = styles.join(';');

  return styleStr;
}

/**
 * Add theme vars to html
 *
 * @param tokens
 */
export function addThemeVarsToHtml(tokens: App.Theme.BaseToken, darkTokens: App.Theme.BaseToken) {
  const cssVarStr = getCssVarByTokens(tokens);
  const darkCssVarStr = getCssVarByTokens(darkTokens);

  const css = `
    html {
      ${cssVarStr}
    }
  `;

  const darkCss = `
    html.${DARK_CLASS} {
      ${darkCssVarStr}
    }
  `;

  const style = document.createElement('style');

  style.textContent = css + darkCss;

  document.head.appendChild(style);
}

/**
 * Toggle css dark mode
 *
 * @param darkMode Is dark mode
 */
export function toggleCssDarkMode(darkMode = false) {
  function addDarkClass() {
    document.documentElement.classList.add(DARK_CLASS);
  }

  function removeDarkClass() {
    document.documentElement.classList.remove(DARK_CLASS);
  }

  if (darkMode) {
    addDarkClass();
  } else {
    removeDarkClass();
  }
}

type NaiveColorScene = '' | 'Suppl' | 'Hover' | 'Pressed' | 'Active';
type NaiveColorKey = `${App.Theme.ThemeColorKey}Color${NaiveColorScene}`;
type NaiveThemeColor = Partial<Record<NaiveColorKey, string>>;
interface NaiveColorAction {
  scene: NaiveColorScene;
  handler: (color: string) => string;
}

/**
 * Get naive theme colors
 *
 * @param colors Theme colors
 */
function getNaiveThemeColors(colors: App.Theme.ThemeColor) {
  const colorActions: NaiveColorAction[] = [
    { scene: '', handler: color => color },
    { scene: 'Suppl', handler: color => color },
    { scene: 'Hover', handler: color => getColorByColorPaletteNumber(color, 500) },
    { scene: 'Pressed', handler: color => getColorByColorPaletteNumber(color, 700) },
    { scene: 'Active', handler: color => addColorAlpha(color, 0.1) }
  ];

  const themeColors: NaiveThemeColor = {};

  const colorEntries = Object.entries(colors) as [App.Theme.ThemeColorKey, string][];

  colorEntries.forEach(color => {
    colorActions.forEach(action => {
      const [colorType, colorValue] = color;
      const colorKey: NaiveColorKey = `${colorType}Color${action.scene}`;
      themeColors[colorKey] = action.handler(colorValue);
    });
  });

  return themeColors;
}

/**
 * Get naive theme
 *
 * @param colors Theme colors
 */
export function getNaiveTheme(colors: App.Theme.ThemeColor) {
  const { primary: colorLoading } = colors;

  const theme: GlobalThemeOverrides = {
    common: {
      ...getNaiveThemeColors(colors)
    },
    Button: {
      borderRadiusMedium: '4px',
      borderRadiusLarge: '4px'
    },
    LoadingBar: {
      colorLoading
    },
    Input: {
      borderRadius: '8px',
      heightMedium: '44px',
      color: 'rgb(var(--layout-bg-color))'
    },
    Modal: {
      peers: {
        Card: {
          colorModal: 'rgb(var(--header-bg-color))',
          borderRadius: '8px'
        }
      }
    },
    Dropdown: {
      optionColorHover: 'rgb(var(--content-hover-color))',
      optionColorActive: 'rgb(var(--content-hover-color))',
      color: 'rgb(var(--siderbar-bg-color))',
      optionTextColor: 'rgb(var(--base-text-color))'
    },
    DataTable: {
      borderRadius: '6px',
      borderColor: 'rgb(var(--header-bg-color))',
      fontSizeLarge: '14px',
      thTextColor: 'rgb(var(--siderbar-text-color))',
      tdTextColor: 'rgb(var(--siderbar-text-color))',
      thColor: 'rgb(var(--table-th-color))',
      tdColor: 'rgb(var(--table-td-color))',
      tdColorHover: 'rgb(var(--content-hover-color))'
    }
  };

  return theme;
}
